
from datetime import datetime
from operator import itemgetter

from tortoise.exceptions import DoesNotExist
from tortoise.transactions import in_transaction

from entity.database.mysql import TestCase
from entity.database.mysql import TestSuite
from exception.custom_exception import CustomErrorThrowException
from utils.createID_tool import ConversationIdGenerator
from entity.schema.testcase_schema import caseDetail
import logging

logger = logging.getLogger(__name__)


# async def delete_testsuite_in_db(suiteId:str):
#     """
#     删除测试集
#     :param suiteId: 测试集id
#     :return: 是否成功
#     """
#     testsuite = await TestSuite.get(suite_id=suiteId)
#     if testsuite is None:
#         return False
#     delete_count = await TestCase.filter(suite_id=suiteId).delete()
#     return delete_count > 0


async def add_testcase_in_db(suiteId:str,detail: caseDetail):
    """
    添加测试用例
    :param detail: 测试用例具体信息
    :param suiteId: 测试集id
    """
    try:
        await TestSuite.get(suite_id=suiteId)

        # 检查用例编号是否重复
        repeated=await TestCase.filter(case_num=detail.casenum,suite_id=suiteId).count()
        if repeated>0:
            logger.error(f"用例编号 {detail.casenum} 已存在")
            raise CustomErrorThrowException(20000,f"用例编号 {detail.casenum} 已存在")

        caseId = ConversationIdGenerator.generate_short_uuid()
        while await TestCase.exists(case_id=caseId):
            logger.error(f"ID冲突: {caseId}，重新生成")
            caseId = ConversationIdGenerator.generate_short_uuid()

        testcase = await TestCase.create(
        case_id=caseId,
        case_num=detail.casenum,
        feature=detail.feature,
        step=detail.steps,
        expected=detail.expected,
        preconditions=detail.preconditions,
        test_scene=detail.scenario,
        suite_id=suiteId,
        created_time=datetime.now(),
        update_time=datetime.now(),
        )
    except DoesNotExist as e:
        logger.error(f"添加测试用例 {detail.casenum} 时发生错误, 测试集不存在", exc_info=True)
        raise CustomErrorThrowException(20000,f"添加测试用例失败")
    except Exception as e:
        logger.error(f"添加测试用例 {detail.casenum} 时发生错误", exc_info=True)
        raise CustomErrorThrowException(20000,f"添加测试用例失败")

    logger.info(f"测试用例 {testcase.case_num} 创建成功")


async def update_testcase_in_db(caseId: str, detail: caseDetail):
    """
    编辑测试用例信息
    :param caseId: 测试用例Id
    :param detail: 测试用例具体信息
    """
    try:
        testcase = await TestCase.get(case_id=caseId)

        testsuite = await TestSuite.get(suite_id=testcase.suite_id)

        # 检查用例编号是否重复
        repeated=await TestCase.filter(case_num=detail.casenum,suite_id=testsuite.suite_id).exclude(case_id=caseId).count()
        if repeated>0:
            logger.warning(f"用例编号 {detail.casenum} 已存在")
            raise CustomErrorThrowException(20000,f"用例编号 {detail.casenum} 已存在")
        # 使用事务确保一致性
        async with in_transaction():
            # 更新测试用例信息
            testcase.feature = detail.feature
            testcase.step = detail.steps
            testcase.case_num = detail.casenum
            testcase.expected = detail.expected
            testcase.preconditions = detail.preconditions
            testcase.update_time = datetime.now()
            testcase.test_scene = detail.scenario
            await testcase.save()

            # 更新测试集更新时间
            testsuite.update_time = datetime.now()
            await testsuite.save()

        logger.info(f"测试用例 {caseId} 更新成功")
    except DoesNotExist as e:
        logger.error(f"更新测试用例 {caseId} 时发生错误, 测试用例或关联测试集不存在", exc_info=True)
        raise CustomErrorThrowException(20000,f"更新测试用例失败")
    except Exception as e:
        logger.error(f"更新测试用例 {caseId} 时发生错误", exc_info=True)
        raise CustomErrorThrowException(20000,f"更新测试用例失败")

async def delete_testcase_in_db(caseId: str):
    """
    删除测试用例
    :param caseId: 测试用例id
    """
    try:
        testcase = await TestCase.get(case_id=caseId)
        test_suite = await TestSuite.get(suite_id=testcase.suite_id)

        # 删除测试用例
        async with in_transaction():
            deleted_count = await TestCase.filter(case_id=caseId).delete()
            if deleted_count > 0:
                logger.info(f"成功删除测试用例 {testcase.case_num}")
                # 更新测试集时间并保存
                test_suite.update_time = datetime.now()
                await test_suite.save()
            else:
                logger.error(f"删除测试用例 {testcase.case_num} 失败")
                raise CustomErrorThrowException(20000,f"删除测试用例 {testcase.case_num} 失败")


    except DoesNotExist as e:
        logger.error(f"更新测试用例 {caseId} 时发生错误, 测试用例或关联测试集不存在", exc_info=True)
        raise CustomErrorThrowException(20000, f"删除测试用例失败")

    except Exception as e:
        logger.error(f"更新测试用例 {caseId} 时发生错误", exc_info=True)
        raise CustomErrorThrowException(20000, f"删除测试用例失败")


async def get_testcases_in_db(suiteId: str):
    """
    获取测试集中的测试用例
    :param suiteId: 测试集编号
    :return: 一个测试集中所有测试用例信息（字典列表），失败返回 None
    """
    try:
        await TestSuite.get(suite_id=suiteId)
        testcases = await TestCase.filter(suite_id=suiteId).values( 'case_id','case_num', 'feature', 'step', 'expected','test_scene'
                                                                    ,'preconditions')
        if testcases:
            logger.info(f"成功获取测试集 {suiteId} 的 {len(testcases)} 条测试用例")
            # 按用例编号和功能排序
            testcases.sort(key=itemgetter('case_num', 'feature'))
        else:
            logger.warning(f"测试集 {suiteId} 中没有找到测试用例")

    except DoesNotExist as e:
        logger.error(f"获取测试集 {suiteId} 的测试用例时发生错误, 测试集不存在", exc_info=True)
        raise CustomErrorThrowException(20000,f"获取测试用例失败")
    except Exception as e:
        logger.error(f"获取测试集 {suiteId} 的测试用例时发生错误", exc_info=True)
        raise CustomErrorThrowException(20000,f"获取测试用例失败")

    return testcases



# async def download_testcases_in_db(suiteId:str,format:int):
#     """
#     下载测试用例
#     :param suiteId: 测试集编号
#     :param format: 测试用例格式(1:word,2:excel,3:CSV)
#     :return: 测试用例信息
#     """
#     testcases = await get_testcases_in_db(suiteId)
#     if testcases is None:
#         return None
#
#     if format == 1:  # Word文档
#         doc = Document()
#         doc.add_heading('测试用例', 0)
#
#         for testcase in testcases:
#             doc.add_heading(f"用例编号: {testcase['case_num']}", level=2)
#             doc.add_paragraph(f"功能点: {testcase['feature']}")
#             doc.add_paragraph(f"步骤: {testcase['step']}")
#             doc.add_paragraph(f"预期结果: {testcase['expected']}")
#             doc.add_paragraph(f"描述: {testcase['description']}")
#             doc.add_paragraph(f"前提条件: {testcase['preconditions']}")
#             doc.add_paragraph("-" * 50)
#
#         # 将文档保存为字节流
#         import io
#         file_stream = io.BytesIO()
#         doc.save(file_stream)
#         file_stream.seek(0)
#         return file_stream.read()
#
#
#     elif format == 2:  # Excel文件
#
#         # 使用pandas生成Excel文件
#
#         import pandas as pd
#
#         import io
#
#         output = io.BytesIO()
#
#         with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
#
#             df = pd.DataFrame(testcases)
#
#             # 选择需要显示的列
#
#             df = df[["case_num", "feature", "step", "expected", "description", "preconditions"]]
#
#             # 重命名列名
#
#             df.columns = ["用例编号", "功能点", "步骤", "预期结果", "描述", "前提条件"]
#
#             df.to_excel(writer, index=False)
#
#         # 获取字节数据
#
#         excel_data = output.getvalue()
#
#         return excel_data
#
#     else:  # CSV文件
#         # 使用csv模块生成CSV文件
#         import csv
#         import io
#         output = io.StringIO()
#         writer = csv.DictWriter(output, fieldnames=[
#             "用例编号", "功能点", "测试步骤", "预期结果",
#             "描述", "前置条件"
#         ])
#
#         writer.writeheader()
#         for testcase in testcases:
#             writer.writerow({
#                 "用例编号": testcase['case_num'],
#                 "功能点": testcase['feature'],
#                 "测试步骤": testcase['step'],
#                 "预期结果": testcase['expected'],
#                 "描述": testcase['description'],
#                 "前置条件": testcase['preconditions']
#             })
#
#         # 获取CSV字节数据
#         return output.getvalue().encode('utf-8-sig')
#
#
#
